﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;

namespace Constriction.Constrict
{
    public class ConstrictionManager
    {
        public const int CONSTRICT_POINT_SPACING = 32;

        public static int numToWiggle = 3;
        public static float wiggleSpeed = 400;

        private List<ConstrictPoint> constrictPoints;

        private Vector2 target;
        private bool readyToWiggle;

        public ConstrictionManager()
        {
            target = new Vector2(400, 300);
            constrictPoints = new List<ConstrictPoint>();
            FillConstrictPoints();
            readyToWiggle = true;
        }

        private void FillConstrictPoints()
        {
            //Top
            for (var x = 16; x < MainGame.SCREEN_WIDTH; x += CONSTRICT_POINT_SPACING)
            {
                constrictPoints.Add(new ConstrictPoint(new Vector2(x, 16)));
            }

            //Right
            for (var y = 16; y < MainGame.SCREEN_HEIGHT; y += CONSTRICT_POINT_SPACING)
            {
                constrictPoints.Add(new ConstrictPoint(new Vector2(MainGame.SCREEN_WIDTH - 16, y))); //Right
            }

            //Bottom Reverse
            for (var x = MainGame.SCREEN_WIDTH - 16; x >= 32; x -= CONSTRICT_POINT_SPACING)
            {
                constrictPoints.Add(new ConstrictPoint(new Vector2(x, MainGame.SCREEN_HEIGHT - 16))); //Bottom
            }

            //Left Reverse
            for (var y = MainGame.SCREEN_HEIGHT - 16; y >= 32; y -= CONSTRICT_POINT_SPACING)
            {
                constrictPoints.Add(new ConstrictPoint(new Vector2(16, y))); //Left
            }
        }

        public void Update(GameTime gameTime)
        {
            bool waitingAtOrigPosition = true;
            bool wiggling = false;

            foreach (var point in constrictPoints)
            {
                point.Update(gameTime, target);
                if (!point.waitingAtOrigPosition)
                {
                    waitingAtOrigPosition = false;
                }

                if (point.isWiggling)
                {
                    wiggling = true;
                }
            }

            if (waitingAtOrigPosition)
            {
                UpdateTarget();

                foreach (var point in constrictPoints)
                {
                    point.waitingAtOrigPosition = false;
                }
            }

            if (!wiggling)
            {
                for (var i = 0; i < numToWiggle; i++)
                {
                    bool wiggleIn = MainGame.rand.Next(100) < 50;

                    var middle = MainGame.rand.Next(1, constrictPoints.Count - 2);

                    constrictPoints[middle - 1].StartWiggling(target, wiggleIn);
                    constrictPoints[middle].StartWiggling(target, wiggleIn);
                    constrictPoints[middle + 1].StartWiggling(target, wiggleIn);
                }
            }
        }

        private void UpdateTarget()
        {
            target.X = MainGame.rand.Next(MainGame.WALL_SIZE, MainGame.SCREEN_WIDTH - MainGame.WALL_SIZE);
            target.Y = MainGame.rand.Next(MainGame.WALL_SIZE, MainGame.SCREEN_HEIGHT - MainGame.WALL_SIZE);
        }

        public void Draw(SpriteBatch batch)
        {
            foreach (var point in constrictPoints)
            {
                point.Draw(batch);
            }
        }

        public bool DoesContactPlayer(Rectangle box)
        {
            return false;
        }

        public Vector2[] GetAllPointVectors()
        {
            var vectors = new List<Vector2>();

            foreach (var point in constrictPoints)
            {
                vectors.Add(point.DrawPosition);
            }

            return vectors.ToArray();
        }

        public VertexPositionColor[] GetAllPointLocations()
        {
            var locations = new List<VertexPositionColor>();

            foreach (var point in constrictPoints)
            {
                locations.Add(new VertexPositionColor(new Vector3(point.DrawPosition.X, point.DrawPosition.Y, 0), Color.Black));
                locations.Add(new VertexPositionColor(new Vector3(point.OrigPosition.X, point.OrigPosition.Y, 0), Color.Black));
            }

            locations.Add(new VertexPositionColor(new Vector3(constrictPoints[0].DrawPosition.X, constrictPoints[0].DrawPosition.Y, 0), Color.Black));
            locations.Add(new VertexPositionColor(new Vector3(constrictPoints[0].OrigPosition.X, constrictPoints[0].OrigPosition.Y, 0), Color.Black));

            return locations.ToArray();
        }
    }
}
